import ExcelJS  from 'exceljs'
import { log } from 'console';
import { readFile } from 'fs/promises';
import path from 'path'
import { URL } from 'url';
import { el, fi } from 'element-plus/es/locales.mjs';

// 模板文件路径（服务端绝对路径）
const OUTPUT_TEMPLATE_PATH = path.join(process.cwd(), 'server/template/OutputTemplate.xlsx');
const INPUT_TEMPLATE_PATH = path.join(process.cwd(), 'server/template/InputTemplate.xlsx');

// 1. 返回模板文件模板
export async function downloadInputTemplate(event ) {
  try {
    // 1. 读取模板文件的二进制数据（Buffer）
    const templateBuffer = await readFile(INPUT_TEMPLATE_PATH);

    // 2. 设置响应头，告诉前端这是一个 Excel 文件，且需要下载
    setResponseHeaders(event, {
      'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // xlsx 格式的 MIME 类型
      'Content-Disposition': 'attachment; filename="InputTemplate.xlsx"', // 下载时的文件名
      'Content-Length': templateBuffer.length.toString(), // 可选：指定文件大小，优化前端下载体验
    });

    // 3. 返回文件的 Buffer 数据（Nuxt 会自动处理为二进制响应）
    return templateBuffer;
  } catch (error) {
    // 处理错误（如文件不存在、读取失败等）
    setResponseStatus(event, 500); // 设置 500 错误状态码
    return { 
      error: '模板文件下载失败', 
      details: (error as Error).message 
    };
  }
}

// 1. 解析前端传过来的excel文件
// 2. 将模板文件的解析结果返回前端
export async function readFrontierInput(input) {
  try {
    // 1. 创建工作簿实例
    const workbook = new ExcelJS.Workbook();
    
    // 2. input已经是前端传过来的excel文件了，读取之
    await workbook.xlsx.load(input.data);
    console.log('Excel文件读取成功');

    // 3. 获取第一个工作表（也可以通过名称获取：workbook.getWorksheet('Sheet1')）
    const worksheet = workbook.getWorksheet(1);
    if (!worksheet) {
      throw new Error('未找到工作表');
    }
    console.log(`当前工作表名称: ${worksheet.name}`);

    const result  = []
    let currentline = 1;
    worksheet.eachRow((row,rowNumber)=>{
        // skip first row
        if(rowNumber==1){
            
        }else{
            // check file format
            if(rowNumber-currentline!=1){
                console.log('file format wrong')
                return
            }
            currentline = rowNumber
            
            const code = row.getCell(1).value
            const drawingNo = row.getCell(2).value
            const name = row.getCell(3).value
            const count = row.getCell(4).value
            const size = row.getCell(5).value
            const weight = row.getCell(6).value
            if(code===null||drawingNo===null||name===null||
                count===null||size===null||weight===null){
                    console.log(`row${rowNumber} format wrong`)
                    return
                }
           
            result.push({
                code,drawingNo,name,count:Number(count),size,weight:Number(weight)
            })
        }
    })

    // console.log(result)

    return result

  } catch (error) {
    console.error('操作Excel失败:', error.message);
  }
}

const getSizeArr = (size)=>{
  return String(size).split(/[xX×\s]/).map((elem) => Number(elem))
}

// 1. 读取模板文件
// 2. 填充模板数据
// 3. 生成结果文件
// 4. 返回前端结果
export async function productfile(dataPak) {
  try {
    //1. 读取模板文件
    const workbook = new ExcelJS.Workbook();
    await workbook.xlsx.readFile(OUTPUT_TEMPLATE_PATH);
    console.log('Excel文件读取成功');

    const worksheet = workbook.getWorksheet(1)
    if (!worksheet) {
      throw new Error('未找到工作表');
    }
    console.log(`当前工作表名称: ${worksheet.name}`);


    // 2. 填充模板数据
    let nextRow = 6

    // 关键：遍历数据时，记录当前索引和元素，便于报错时定位
    // dataPak.forEach((element, index) => {
    //   try {
    //     // 打印当前处理的索引和元素（关键上下文）
    //     console.log(`正在处理第 ${index+1} 条数据：`, JSON.stringify(element, null, 2));
    //     const rows = getRows(element);
    //     worksheet.insertRows(nextRow, rows);
    //     nextRow += rows.length; // 修复原逻辑：更新 nextRow
    //   } catch (error) {
    //     // 捕获单条数据处理的错误，避免整个循环中断
    //     throw new Error(`处理第 ${index+1} 条数据时失败：${(error as Error).message}`, {
    //       cause: error // 传递原始错误，保留错误栈
    //     });
    //   }
    // });


    const fill = {
    type: 'pattern',
    pattern: 'solid', // 纯色填充
    fgColor: { argb: '80E6F7FF' } // ARGB 颜色值（FF 是透明度，后面是 RGB）
  };

    dataPak.forEach((element) =>{
      // console.log(element)
      const rows = getRows(element)
      // // // console.log(rows);
      rows.forEach( (row,index)=>{
        if(index==0){
          const firstRow  =  worksheet.insertRow(nextRow++,row)
          firstRow.eachCell(cell=> {cell.fill = fill})
        }else{
          worksheet.insertRow(nextRow++,row)
        }
      })
    });

    //   (element,index) => {
    //   const code = element['code'];
    //   const drawingNo = element['drawingNo'];
    //   const name = element['name'];
    //   const count = element['count'];
    //   const size = element['size'];
    //   const sizeArr = element['sizeArr'];
    //   const weight = element['weight'];
      
    //   // console.log(code,drawingNo,name,count,size,sizeArr,weight)
    //   const currentRow = worksheet.insertRow(nextRow)
      
    //   // A	序号	   B	物料号	C	图号	D	工装名
    //   // E	材料	   F	用量	G	规格尺寸	H	材料定额
    //   // I	材料单价	J	净重	K	回收单价	L	原材料费
    //   // M	工序名字	N	设备型号	O	工时定额	P	工序单价
    //   // Q	工序费用	R	财务费率	S	财务费用	T	管理费率
    //   // U	管理费用	V	运费费率	W	运费费用	X	利润率
    //   // Y	利润	   Z	核算总价				


    //   currentRow.getCell(`A`).value =index+1 
    //   currentRow.getCell(`B`).value = code
    //   currentRow.getCell(`C`).value = drawingNo
    //   currentRow.getCell(`D`).value = name
    //   currentRow.getCell(`F`).value = count 
    //   currentRow.getCell(`G`).value = size
    //   currentRow.getCell(`H`).value = sizeArr.reduce((acc, curr) => acc*curr,1)/1e6*7.89
    //   //材料费
    //   currentRow.getCell(`I`).value = 1
    //   currentRow.getCell(`J`).value = weight
    //   //回收单价
    //   currentRow.getCell(`K`).value = 6
    //   currentRow.getCell(`L`).value = {
    //     formula: `H${nextRow}*I${nextRow}-K${nextRow}*(H${nextRow}-J${nextRow})`
    //   }
    //   nextRow++
    // }

    setBorderForRange(worksheet,6,nextRow,'A','Z')
    
    // 3. 生成结果文件, 生成文件Buffer（关键步骤）
    const buffer = await workbook.xlsx.writeBuffer(); // 将工作簿转换为二进制Buffer
    console.log('Excel文件生成成功，大小：', buffer.length);


    await $fetch('/api/hejia',{
      method:'POST',
      body: dataPak
    })

    // 4. 返回前端
    return buffer; 

  } catch (error) {
    console.error('操作Excel失败:', error.message);
  }
}

/**
 * 给指定区域添加全部框线
 * @param worksheet 工作表实例
 * @param startRow 起始行（如 1）
 * @param endRow 结束行（如 3）
 * @param startCol 起始列（如 'A'）
 * @param endCol 结束列（如 'C'）
 * @param borderStyle 边框样式（可选，默认细实线）
 */
function setBorderForRange(
  worksheet: ExcelJS.Worksheet,
  startRow: number,
  endRow: number,
  startCol: string,
  endCol: string,
  borderStyle: ExcelJS.Border = {
    top: { style: 'thin' },
    left: { style: 'thin' },
    bottom: { style: 'thin' },
    right: { style: 'thin' }
  }
) {
  // 遍历区域内的所有行
  for (let rowNum = startRow; rowNum <= endRow; rowNum++) {
    const row = worksheet.getRow(rowNum);
    // 遍历行内的所有列（从 startCol 到 endCol）
    for (let col = startCol; col <= endCol; col = String.fromCharCode(col.charCodeAt(0) + 1)) {
      const cell = row.getCell(col);
      // 设置单元格边框
      cell.border = borderStyle;
    }
    row.commit(); // 提交行修改
  }
}

/**
 * 读入前端的零件数据，读入给他分配的价格，返回这个零件的表格行
 * @param data 用于生成part表格行的数据
 * @param price 这个零件的价格
 */
function compilePart(data) {  
  // 1. 计算运费= 净重×0.3
  const transprot = 0.3 * data.weight
  let currentPrice = data.price - transprot

  // 2. 计算总费用
  let sum = currentPrice / 1.21
  const finance = sum * 0.03
  const manage = sum * 0.08 
  const profit = sum * 0.1

  // 3. 读取数据
  const code = data['code'];
  const drawingNo = data['drawingNo'];
  const name = data['name'];
  const count = data['count'];
  const size = data['size'];
  const sizeArr = getSizeArr(size)
  const weight = data['weight'];
  const commonpart = data['commonpart']


  // 4. 创建行封装数据

  // A	序号	   B	物料号	C	图号	D	工装名
  // E	材料	   F	用量	G	规格尺寸	H	材料定额
  // I	材料单价	J	净重	K	回收单价	L	原材料费
  // M	工序名字	N	设备型号	O	工时定额	P	工序单价
  // Q	工序费用	R	财务费率	S	财务费用	T	管理费率
  // U	管理费用	V	运费费率	W	运费费用	X	利润率
  // Y	利润	   Z	核算总价			
  
  const maopi = sizeArr.reduce((acc, curr) => acc*curr,1)/1e6*7.89

  // console.log(sizeArr)
  // console.log('maopi',maopi)

  const materialPrice = commonpart.material.price*maopi - commonpart.material.recycle * (maopi- weight)

  const rows = create2DArray(commonpart.steps.length > 1 ? commonpart.steps.length:1)

  rows[0][1] = code
  rows[0][2] = drawingNo
  rows[0][3] = name

  if(commonpart.material.name){
    rows[0][4] = commonpart.material.name
    rows[0][5] = count
    rows[0][6] = size
    rows[0][7] = maopi
    rows[0][8] = commonpart.material.price
    rows[0][9] = weight
    rows[0][10] = commonpart.material.recycle
    rows[0][11] = materialPrice
    //纯工费
    sum -= materialPrice
  }


  // 费用常数部分
  rows[0][17] = 0.03
  rows[0][19] = 0.08
  rows[0][21] = 0.3
  rows[0][23] = 0.1

  // 费用计算部分
  // 财务
  rows[0][18] = finance
  // 管理
  rows[0][20] = manage
  // 运输
  rows[0][22] = transprot
  // 利润
  rows[0][24] = profit

  //总价
  rows[0][25] = data.price

  //纯工时
  const laborTime = sum / commonpart.average
  
  //工序部分
  for(let i = 0;i< commonpart.steps.length;i++){
    // 工序名
    rows[i][12] = commonpart.steps[i].name
    // 设备名字
    rows[i][13] = commonpart.steps[i].equipment
    // 工时
    rows[i][14] = laborTime * commonpart.steps[i].weighting/100
    // 工序单价
    rows[i][15] = commonpart.steps[i].price
    // 工序费用
    rows[i][16] = rows[i][15] * rows[i][14]
  }

  return rows
}

/**
 * 
 * @param n 创建二维数组26列n行
 * @returns 
 */
function create2DArray(n) {
  // 生成 n 行，每行是一个长度为 26 的数组
  return Array.from({ length: n }, () => new Array(26).fill(''));
}

function compileAsm(dataAsm){
  const result = []
  // 1. 通过总成占比，计算总成价格，将总成部分视为一个零件
  const inAllPriceToStore = dataAsm.price
  dataAsm.price = inAllPriceToStore * dataAsm.commonpart.asm.ratio / 100
  result.push(...compilePart(dataAsm))
  // 2. 根据子件重量分配价格
  const childPriceInTotal = inAllPriceToStore - dataAsm.price // 子件总价格
  dataAsm.children.forEach(child =>{
    child.price = childPriceInTotal * child.weight /  dataAsm.weight
    // 3. 遍历所有零件，子件，调用compilePrt，组装返回行
    result.push(...compilePart(child))
  })
  // 4. 返回总成核价行
  return result;
}

function getRows(element) {
  if(element.commonpart.asm.tag){
    return compileAsm(element)
  }
    return compilePart(element)
  
}
